package org.javarosa.mesh4j.sync.adapter;

import java.util.Date;
import java.util.Vector;

import javax.microedition.rms.RecordEnumeration;

import org.javarosa.core.JavaRosaServiceProvider;
import org.javarosa.core.services.storage.utilities.IRecordStoreEnumeration;
import org.javarosa.user.model.User;
import org.javarosa.user.storage.UserRMSUtility;
import org.kxml2.kdom.Element;
import org.mesh4j.sync.adapters.rms.storage.EntityContent;
import org.mesh4j.sync.adapters.split.IContentAdapter;
import org.mesh4j.sync.model.IContent;
import org.mesh4j.sync.utils.XmlHelper;
import org.mesh4j.sync.validations.Guard;
import org.mesh4j.sync.validations.MeshException;

public class UserContentAdapter implements IContentAdapter {

	// MODEL VARIABLES
	private String rmsName;
	private UserRMSUtility rmsUtility;
	
	// BUSINESS METHODS
	
	public UserContentAdapter(String rmsName){
		Guard.argumentNotNullOrEmptyString(rmsName, "rmsName");		
		this.rmsName = rmsName;
		this.rmsUtility = (UserRMSUtility)JavaRosaServiceProvider.instance().getStorageManager().getRMSStorageProvider().getUtility(rmsName);
		Guard.argumentNotNull(this.rmsUtility, "rmsUtility");
	}
	
	public String getType() {
		return this.rmsName;
	}
	
	public void delete(IContent entity) {
		User user = this.getUser(entity.getId());
		if(user == null){
			return;
		}
		this.getRmsUtility().deleteRecord(user.getRecordId());
	}

	public IContent get(String entityId) {
		User user = this.getUser(entityId);
		if(user == null){
			return null;
		}
		
		String payload = formatUser(user);
		EntityContent content = new EntityContent(payload, "user", entityId);
		return content;
	}

	public Vector<IContent> getAll(Date since) {
		Vector<IContent> result = new Vector<IContent>();
		
		IRecordStoreEnumeration records = null;
		try {
			records = this.rmsUtility.enumerateMetaData();
			
			int size = records.numRecords();
			if(size == 0){
				return result;
			}
			
			int index = -1;
			User user = new User();
			IContent content = null;
			while (records.hasNextElement()){
				index = records.nextRecordId();
				this.rmsUtility.retrieveFromRMS(index, user);
				content = new EntityContent(formatUser(user), "user", user.getUsername().trim());
				result.addElement(content);
			}
		} catch (Exception e) {
			e.printStackTrace();
			throw new MeshException(e.getMessage());
		}finally{
			if(records != null){
				records.destroy();
			}
		}
		return result;
	}

	public void save(IContent content) {
		EntityContent entity = EntityContent.normalizeContent(content, "user", "name");
		User newUser = this.parseUser(entity.getPayload());
		User user = this.getUser(entity.getId());
		if(user == null){
			this.getRmsUtility().writeToRMS(newUser, null);
		} else {
			newUser.setRecordId(user.getRecordId());
			this.getRmsUtility().updateToRMS(user.getRecordId(), newUser, null);
		}
	}

	private UserRMSUtility getRmsUtility(){
		return this.rmsUtility;
	}
	
	private User getUser(String name){
		UserRMSUtility userRMS = this.getRmsUtility();
		int size = userRMS.getNumberOfRecords();
		if(size == 0){
			return null;
		}
		
		User discoveredUser = new User();
		int index = 1;
		while (index <= size){
			try{
				userRMS.retrieveFromRMS(index, discoveredUser);
			} catch (Exception e) {
				e.printStackTrace();
				throw new MeshException(e.getMessage());
			}
			
			if (discoveredUser.getUsername().trim().equals(name.trim())){
				discoveredUser.setRecordId(index);
				return discoveredUser;
			} 
			index = index + 1;
		}
		return null;
	}
	

	public static String formatUser(User user) {
		StringBuffer sb = new StringBuffer();
		sb.append("<user>");
		
		sb.append("<type>");
		sb.append(user.getUserType());
		sb.append("</type>");

		sb.append("<name>");
		sb.append(user.getUsername());
		sb.append("</name>");
		
		sb.append("<password>");
		sb.append(user.getPassword());
		sb.append("</password>");
		sb.append("</user>");
		return sb.toString();
	}
	
	public User parseUser(String payload){
		Element root = XmlHelper.getElement(payload);
		String name = root.getElement(null, "name").getText(0);
		String password = root.getElement(null, "password").getText(0);
		String type = root.getElement(null, "type").getText(0);
		return new User(name.trim(), password.trim(), type.trim());
	}

	public void deleteAll() {
		IRecordStoreEnumeration records = null;
		try {
			records = this.rmsUtility.enumerateMetaData();
			int recordId;
			while(records.hasNextElement()){
				recordId = records.nextRecordId();
				this.rmsUtility.deleteRecord(recordId);
			}
		} catch(Exception e) {
			e.printStackTrace();
			throw new MeshException(e.getMessage());
		}finally{
			if(records != null){
				records.destroy();
			}
		}
	}

	public void deleteRecordStorage() {
		this.rmsUtility.close();
		this.rmsUtility.delete();
	}

	public IContent normalize(IContent content) {
		return EntityContent.normalizeContent(content, "user", "name");
	}
}
